package com.xingda.packing.dmds.plc.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xingda.packing.dmds.plc.entity.PlcItem;
import com.xingda.packing.dmds.plc.entity.PlcItemVal;
import com.xingda.packing.dmds.plc.service.PlcConnService;
import com.xingda.packing.dmds.plc.service.PlcHandleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.plc4x.java.api.messages.PlcReadRequest;
import org.apache.plc4x.java.api.messages.PlcReadResponse;
import org.apache.plc4x.java.api.messages.PlcWriteRequest;
import org.apache.plc4x.java.api.messages.PlcWriteResponse;
import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component("plcHandleDMDSService")
@Slf4j
public class PlcHandleServiceImpl implements PlcHandleService {


    @Resource
    private PlcConnService plcConnService;

    @Override
    public JSONObject readItem(PlcItem... plcItems) {

        if (!plcConnService.getConn().getMetadata().canRead()) {
            return null;
        }
        JSONObject fieldValueJson = new JSONObject();

        PlcReadRequest.Builder builder = plcConnService.getConn().readRequestBuilder();

        for (PlcItem plcItem : plcItems) {
            builder.addItem(plcItem.getName(), plcItem.getFieldQuery());
        }
        PlcReadRequest readRequest = builder.build();
        PlcReadResponse response;
        try {
            response = readRequest.execute().get(10000, TimeUnit.MILLISECONDS);
            for (String fieldName : response.getFieldNames()) {
                if (response.getResponseCode(fieldName) == PlcResponseCode.OK) {
                    int numValues = response.getNumberOfValues(fieldName);
                    if (numValues == 1) {
                        fieldValueJson.put(fieldName, response.getObject(fieldName));
                    } else {
                        fieldValueJson.put(fieldName, response.getAllObjects(fieldName));
                    }
                } else {
                    log.error("Error[" + fieldName + "]: " + response.getResponseCode(fieldName).name());
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return fieldValueJson.keySet().size() > 0 ? fieldValueJson : null;

    }

    @Override
    public boolean writeItem(PlcItemVal... plcItemVals) {
        if (!plcConnService.getConn().getMetadata().canWrite()) {
            return false;
        }
        PlcWriteRequest.Builder builder = plcConnService.getConn().writeRequestBuilder();
        for (PlcItemVal plcItemVal : plcItemVals) {
            builder.addItem(plcItemVal.getName(), plcItemVal.getFieldQuery(), plcItemVal.getValues());
        }
        PlcWriteRequest writeRequest = builder.build();
        try {
            PlcWriteResponse response = writeRequest.execute().get(10000, TimeUnit.MILLISECONDS);
            for (String fieldName : response.getFieldNames()) {
                if (response.getResponseCode(fieldName) == PlcResponseCode.OK) {
                    if (!fieldName.equals("MES心跳")) {
                        log.info(fieldName + "-------- 写入成功!");
                    }
                } else {
                    log.error("Error[" + fieldName + "]-------- 写入失败! " + response.getResponseCode(fieldName).name());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public boolean writeItem(List<PlcItemVal> plcItemVals) {
        PlcItemVal[] plcItemValArray = new PlcItemVal[plcItemVals.size()];
        plcItemVals.toArray(plcItemValArray);
        if (plcItemVals.size() == 1 && plcItemVals.get(0).getName().equals("MES心跳")) {
            return writeItem(plcItemValArray);
        }
        log.info("PLC写入信息{}", plcItemVals);
        return writeItem(plcItemValArray);
    }

}
